//
//  OperatorBindable.swift
//  CSBind
//
//  Created by 万孟超 on 2023/12/22.
//

import Foundation

protocol CSOperatorBindable { }

extension CSOperatorBindable {
    
    func create<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ binder: RT?, _ binderKeyPath: ReferenceWritableKeyPath<RT, ValueType>) -> Any where LT: NSObject, RT : NSObject, ValueType: Any {
        weak var weakBinder = binder
        weak var weakTarget = target
        let bindOperator = CSBindOperator<RT, LT, ValueType>(bindTarget: weakBinder, bindKeyPath: binderKeyPath)
        bindOperator.bind(on: weakTarget, keyPath: targetKeyPath)
        return bindOperator
    }
    
    func create<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: String, _ binder: RT?, _ binderKeyPath: ReferenceWritableKeyPath<RT, ValueType>)  -> Any where LT: NSObject, RT: NSObject, ValueType: Any {
        weak var weakBinder = binder
        weak var weakTarget = target
        let bindOperator = CSBindOperator(bindTarget: weakBinder, bindKeyPath: binderKeyPath)
        bindOperator.bind(on: weakTarget, keyPath: targetKeyPath)
        return bindOperator
    }
    
    func create<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ binder: RT?, _ binderKeyPath: String)  -> Any where LT: NSObject, RT: NSObject, ValueType: Any {
        weak var weakBinder = binder
        weak var weakTarget = target
        let bindOperator = CSBindOperator<RT, LT, ValueType>(bindTarget: weakBinder, binderKeyPathString: binderKeyPath)
        bindOperator.bind(on: weakTarget, keyPath: targetKeyPath)
        return bindOperator
    }
    
    func create<LT, RT>(_ target: LT?, _ targetKeyPath: String, _ binder: RT?, _ binderKeyPath: String)  -> Any where LT: NSObject, RT: NSObject {
        weak var weakBinder = binder
        weak var weakTarget = target
        let bindOperator = CSBindOperator<RT, LT, Any>(bindTarget: weakBinder, binderKeyPathString: binderKeyPath)
        bindOperator.bind(on: weakTarget, keyPath: targetKeyPath)
        return bindOperator
    }
    
    static func create<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ binder: RT?, _ binderKeyPath: ReferenceWritableKeyPath<RT, ValueType>) -> Any where LT: NSObject, RT : NSObject, ValueType: Any {
        weak var weakBinder = binder
        weak var weakTarget = target
        let bindOperator = CSBindOperator<RT, LT, ValueType>(bindTarget: weakBinder, bindKeyPath: binderKeyPath)
        bindOperator.bind(on: weakTarget, keyPath: targetKeyPath)
        return bindOperator
    }
    
    static func create<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: String, _ binder: RT?, _ binderKeyPath: ReferenceWritableKeyPath<RT, ValueType>)  -> Any where LT: NSObject, RT: NSObject, ValueType: Any {
        weak var weakBinder = binder
        weak var weakTarget = target
        let bindOperator = CSBindOperator(bindTarget: weakBinder, bindKeyPath: binderKeyPath)
        bindOperator.bind(on: weakTarget, keyPath: targetKeyPath)
        return bindOperator
    }
    
    static func create<LT, RT, ValueType>(_ target: LT?, _ targetKeyPath: ReferenceWritableKeyPath<LT, ValueType>, _ binder: RT?, _ binderKeyPath: String)  -> Any where LT: NSObject, RT: NSObject, ValueType: Any {
        weak var weakBinder = binder
        weak var weakTarget = target
        let bindOperator = CSBindOperator<RT, LT, ValueType>(bindTarget: weakBinder, binderKeyPathString: binderKeyPath)
        bindOperator.bind(on: weakTarget, keyPath: targetKeyPath)
        return bindOperator
    }
    
    static func create<LT, RT>(_ target: LT?, _ targetKeyPath: String, _ binder: RT?, _ binderKeyPath: String)  -> Any where LT: NSObject, RT: NSObject {
        weak var weakBinder = binder
        weak var weakTarget = target
        let bindOperator = CSBindOperator<RT, LT, Any>(bindTarget: weakBinder, binderKeyPathString: binderKeyPath)
        bindOperator.bind(on: weakTarget, keyPath: targetKeyPath)
        return bindOperator
    }
}
